"""
装饰器：装饰器通常是一个函数，它可以装饰另一个函数或类，为其提供额外的能力
这些额外的能力，通常跟正常的业务代码没有必然联系，称为横切关注功能（cross concern）
装饰器实现了设计模式中的代理模式（用代理对象执行被代理对象的行为并执行额外的行为）
1995 GoF 23种场景 ---> Design Pattern ---> 如何设计类以及类之间的关系
"""
import random
import time

from functools import wraps, partial

import MySQLdb


class RecordTime:

    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        start = time.time()
        result = self.func(*args, **kwargs)
        end = time.time()
        print(f'{self.func.__name__}执行时间: {end - start:.3f}秒')
        return result


def record_time(make_log):

    def decorator(func):

        @wraps(func)
        def wrapper(*args, **kwargs):
            start = time.time()
            result = func(*args, **kwargs)
            end = time.time()
            make_log(func.__name__, end - start)
            return result

        return wrapper

    return decorator


def console_output(fname, duration):
    print(f'{fname}执行时间: {duration:.3f}秒')


def file_output(fname, duration, *, file_path):
    with open(file_path, 'a') as file:
        file.write(f'{fname}执行时间: {duration:.3f}秒\r\n')


output1 = partial(file_output, file_path='result.log')
output2 = partial(file_output, file_path='hello.log')


def db_output(fname, duration):
    conn = MySQLdb.connect(host='47.104.31.138', port=3306,
                           user='root', password='Luohao.618',
                           database='hrs', charset='utf8')
    try:
        with conn.cursor() as cursor:
            cursor.execute(
                'insert into tb_log values (default, %s, %s)',
                (fname, duration)
            )
        conn.commit()
    except MySQLdb.MySQLError:
        conn.rollback()
    finally:
        conn.close()


# download = record_time(console_output)(download)
# @record_time(db_output)
# download = RecordTime(download)
# download(...) ---> RecordTime ---> __call__
@RecordTime
def download(filename):
    print(f'开始下载{filename}...')
    time.sleep(random.random() * 3 + 3)
    print(f'{filename}下载完成...')


# upload = record_time(file_output)(upload)
@record_time(output1)
def upload(filename):
    print(f'开始上传{filename}...')
    time.sleep(random.random() * 4 + 4)
    print(f'{filename}上传完成...')


# print(download.__name__)
download('Python从入门到住院.pdf')
upload('北京有点热.avi')

# download.__wrapped__('MySQL从删库到跑路.pdf')
